import fs from "fs";
import { URL } from "url";
import http from "http";

import FormData from "form-data";
import axios, { AxiosInstance, AxiosRequestConfig } from "axios";

import { APPID } from "./constant";

type HttpMethod = "GET" | "POST";

export class ApiClient {
  private readonly client: AxiosInstance;
  private readonly baseUrl: string;

  constructor(baseUrl: string) {
    this.baseUrl = baseUrl;

    // 配置 Axios 实例
    this.client = axios.create({
      timeout: 600000, // 60秒超时
      maxContentLength: Infinity,
      maxBodyLength: Infinity,
      // 连接池配置（Axios 底层使用 http.Agent）
      httpAgent: new http.Agent({
        keepAlive: true,
        maxSockets: 100,
        timeout: 300000, // 5分钟
      }),
    });
  }

  // 通用请求验证方法
  private validateParams(...params: any[]): void {
    if (params.some((p) => p === undefined || p === null || p === "")) {
      throw new Error("Parameters cannot be null or empty");
    }
  }

  // 通用请求构造器
  private async executeRequest<T>(
    method: HttpMethod,
    url: string,
    headers: Record<string, string>,
    data?: any,
  ): Promise<T> {
    const config: AxiosRequestConfig = {
      method,
      url,
      headers,
      data,
      validateStatus: () => true, // 自行处理状态码
    };

    try {
      const response = await this.client.request(config);

      if (response.status >= 400) {
        throw new Error(
          `Unexpected code: ${response.status}, ${response.data}`,
        );
      }

      return response.data;
    } catch (error) {
      if (error instanceof Error) {
        throw new Error(`Request failed: ${error.message}`);
      }
      throw error;
    }
  }

  // 模板列表接口
  public async getTemplateList(
    timestamp: string,
    signature: string,
  ): Promise<any> {
    this.validateParams(timestamp, signature);

    const payload = {
      style: "商务",
      pageSize: "10",
    };

    return this.executeRequest(
      "POST",
      `${this.baseUrl}/template/list`,
      {
        appId: APPID,
        timestamp: timestamp,
        signature: signature,
        "Content-Type": "application/json; charset=utf-8",
      },
      payload,
    );
  }

  // 创建大纲（表单方式）
  public async createOutline(
    timestamp: string,
    signature: string,
    query: string,
  ): Promise<any> {
    this.validateParams(timestamp, signature, query);

    const form = new FormData();

    form.append("query", query);

    return this.executeRequest(
      "POST",
      `${this.baseUrl}/createOutline`,
      {
        appId: APPID,
        timestamp: timestamp,
        signature: signature,
        ...form.getHeaders(),
      },
      form,
    );
  }

  // 通过文档创建大纲（文件上传）
  public async createOutlineByDoc(
    timestamp: string,
    signature: string,
    templateId: string,
    filePath: string,
  ): Promise<any> {
    this.validateParams(timestamp, signature);

    const form = new FormData();
    const fileStream = fs.createReadStream(filePath);

    form.append("file", fileStream);
    form.append("fileName", filePath.split("/").pop() || "");

    return this.executeRequest(
      "POST",
      `${this.baseUrl}/createOutlineByDoc`,
      {
        appId: APPID,
        templateId: templateId,
        timestamp: timestamp,
        signature: signature,
        ...form.getHeaders(),
      },
      form,
    );
  }

  // 创建PPT（文件上传）
  public async create(
    timestamp: string,
    signature: string,
    content: string,
    templateId: string,
  ): Promise<any> {
    this.validateParams(timestamp, signature);

    // 创建临时文件并写入内容
    const tempFilePath = `temp_${Date.now()}.txt`;

    fs.writeFileSync(tempFilePath, content, "utf-8");

    const form = new FormData();
    const fileStream = fs.createReadStream(tempFilePath);

    form.append("file", fileStream);
    form.append("fileName", tempFilePath);
    form.append("templateId", templateId);

    return this.executeRequest(
      "POST",
      `${this.baseUrl}/create`,
      {
        appId: APPID,
        timestamp: timestamp,
        signature: signature,
        ...form.getHeaders(),
      },
      form,
    );
  }

  // 通过大纲创建PPT
  public async createPptByOutline(
    timestamp: string,
    signature: string,
    outline: string,
  ): Promise<any> {
    this.validateParams(timestamp, signature);

    const payload = {
      outline: JSON.parse(outline),
      query: "test",
    };

    return this.executeRequest(
      "POST",
      `${this.baseUrl}/createPptByOutline`,
      {
        appId: APPID,
        timestamp: timestamp,
        signature: signature,
        "Content-Type": "application/json; charset=utf-8",
      },
      payload,
    );
  }

  // 检查进度
  public async checkProgress(
    timestamp: string,
    signature: string,
    sid: string,
  ): Promise<any> {
    this.validateParams(timestamp, signature, sid);

    const url = new URL(`${this.baseUrl}/progress`);

    url.searchParams.append("sid", sid);

    return this.executeRequest("GET", url.toString(), {
      appId: APPID,
      timestamp: timestamp,
      signature: signature,
    });
  }
}

export const apiClient = new ApiClient("https://zwapi.xfyun.cn/api/ppt/v2");
